package com.kedacom.freedomLabel.view.fragment;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;

import com.google.gson.Gson;
import com.kedacom.freedomLabel.Options;
import com.kedacom.freedomLabel.R;
import com.kedacom.freedomLabel.base.BaseFragment;
import com.kedacom.freedomLabel.databinding.FragmentListDataBinding;
import com.kedacom.freedomLabel.model.DataControlResult;
import com.kedacom.freedomLabel.model.bean.IFirstLetter;
import com.kedacom.freedomLabel.model.db.DataCallback;
import com.kedacom.freedomLabel.model.db.DataLoader;
import com.kedacom.freedomLabel.model.db.dao.IDao;
import com.kedacom.freedomLabel.utils.log.LLog;
import com.kedacom.freedomLabel.view.widget.decoration.IDStickyItemDecoration;
import com.kedacom.freedomLabel.viewmodel.ListDataViewModel;
import com.kedacom.lego.adapter.recyclerview.LegoBaseRecyclerViewAdapter;
import com.kedacom.lego.annotation.ContentView;
import com.kedacom.lego.annotation.OnMessage;
import com.kedacom.lego.annotation.ViewModel;
import com.kedacom.lego.fast.widget.refreshlayout.util.DensityUtil;
import com.kedacom.lego.message.LegoMessageManager;

import java.util.ArrayList;
import java.util.function.Consumer;


@ContentView(R.layout.fragment_list_data)
@ViewModel(ListDataViewModel.class)
public class ListDataFragment<T extends IFirstLetter> extends BaseFragment<FragmentListDataBinding, ListDataViewModel<T>> {

    private boolean mShouldScroll; // 目标项是否在最后一个可见项之后
    private int mToPosition;       // 记录目标项位置
    private boolean isPickMode;    // 是否是选择人员模式

    Handler mHandler = new Handler();
    Context mContext;
    View mRootView;

    int mSelectPosition = -1;
    IDao<T> mDao;
    IFirstLetterAdapter<T> mAdapter;
    String mParam1, mParam2;
    boolean isShowSearchView;

    public static <T extends IFirstLetter> ListDataFragment<T> newInstance(@NonNull IDao<T> dao) {
        return newInstance(dao, null, true);
    }

    public static <T extends IFirstLetter> ListDataFragment<T> newInstance(@NonNull IDao<T> dao, boolean isShowSearchView) {
        return newInstance(dao, null, isShowSearchView);
    }

    public static <T extends IFirstLetter> ListDataFragment<T> newInstance(@NonNull IDao<T> dao, @Nullable String param1, boolean isShowSearchView) {
        ListDataFragment<T> fragment = new ListDataFragment<>();
        fragment.mDao = dao;
        fragment.mParam1 = param1;
        fragment.isShowSearchView = isShowSearchView;
        return fragment;
    }

    @OnMessage(value = Options.MSG_UPDATE_LIST_PARAM, always = true)
    public void setArguments(String[] params) {
        mParam1 = params[0];
        mParam2 = params[1];
        mViewModel.getDataList(mDao, mParam1, mParam2);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mHandler.removeCallbacksAndMessages(null);
        mContext = null;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        if (mRootView == null) {
            mRootView = super.onCreateView(inflater, container, savedInstanceState);
            initView();
            initAdapter();
            mViewModel.getDataLiveData().observe(this, data -> {
                // 复原数据
                mSelectPosition = -1;
                mAdapter.setData(mViewModel.mDataList);
            });
        }
        return mRootView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mViewModel.getDataList(mDao, mParam1, mParam2);
    }

    private void initView() {
        if (isShowSearchView) {
            mBinding.searchLayout.setVisibility(View.VISIBLE);
            initSearchView();
        } else {
            mBinding.searchLayout.setVisibility(View.GONE);
        }
        mBinding.recycler.setLayoutManager(new LinearLayoutManager(getContext()));
        mBinding.recycler.addItemDecoration(new IDStickyItemDecoration<>(mContext,
                mViewModel.mDataList));
        mBinding.sideBar.setTextView(mBinding.sideTipView);
        mBinding.sideBar.setOnTouchingLetterChangedListener((s, y) -> {
            int position = getPositionFormSection(s.charAt(0));
            if (position != -1) {
                moveToPosition(position + mAdapter.getHeaderLayoutCount(), mBinding.recycler);
            }
            if (y > 0 && y < mBinding.sideBar.getHeight()) {
                moveSideBarTip(y);
            }
        });
        mBinding.sideBar.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
            if (mShouldScroll) {
                mShouldScroll = false;
                moveToPosition(mToPosition, mBinding.recycler);
            }
        });
        mBinding.recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int firstItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0));
                if (firstItem >= 0) {
                    T item = mAdapter.getData().get(firstItem);
                    mBinding.sideBar.onSelected(item.getFirstLetter());
                }
            }
        });
    }

    /**
     * 初始化搜索控件
     */
    protected void initSearchView() {
        mBinding.searchText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (s.length() > 0) {
                    if (mBinding.searchClear.getVisibility() == View.INVISIBLE) {
                        mBinding.searchClear.setVisibility(View.VISIBLE);
                        mBinding.searchClear.setClickable(true);
                    }
                } else {
                    if (mBinding.searchClear.getVisibility() == View.VISIBLE) {
                        mBinding.searchClear.setVisibility(View.INVISIBLE);
                        mBinding.searchClear.setClickable(false);
                    }
                }
                mParam2 = s.toString().trim();
            }
        });

        mBinding.searchText.setOnEditorActionListener((v, actionId, event) -> {
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                closeSoftKeyboard();
                LLog.debug("关键字搜索 " + mParam2);
                mViewModel.getDataList(mDao, mParam1, mParam2);
                return true;
            }
            return false;
        });

        mBinding.searchClear.setOnClickListener(v -> {
            mBinding.searchText.setText(null);
            mParam2 = null;
            mViewModel.getDataList(mDao, mParam1, null);
            closeSoftKeyboard();
        });
    }

    private void closeSoftKeyboard() {
        if (mContext != null) {
            View currentFocusView = getActivity().getCurrentFocus();
            if (currentFocusView != null) {
                InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(currentFocusView.getWindowToken(), 0);
            }
        }
    }

    private void initAdapter() {
        mAdapter = new IFirstLetterAdapter<>(new ArrayList<>());
        mAdapter.setOnItemClickListener((LegoBaseRecyclerViewAdapter.OnItemClickListener<T>) (view, data, position) -> {
            beep();
            if (mSelectPosition != -1) {
                mAdapter.getData().get(mSelectPosition).setSelected(false);
                mAdapter.notifyItemChanged(mSelectPosition);
            }
            mSelectPosition = position;
            data.setSelected(true);
            mAdapter.notifyItemChanged(mSelectPosition);

            mSelectPosition = position;
            // 发送选中项目
            LegoMessageManager.getInstance().sendMessage(Options.MSG_SELECT_ITEM, data);
            LLog.debug(new Gson().toJson(data));
        });
        mBinding.recycler.setAdapter(mAdapter);
    }

    private int getPositionFormSection(char section) {
        for (int i = 0; i < mAdapter.getData().size(); i++) {
            String sortStr = mAdapter.getData().get(i).getFirstLetter();
            char firstChar = sortStr.toUpperCase().charAt(0);
            if (firstChar == section) {
                return i;
            }
        }
        return -1;
    }

    public void moveToPosition(int position, RecyclerView recyclerView) {
        // 第一个可见位置
        int firstItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0));
        // 最后一个可见位置
        int lastItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(recyclerView.getChildCount() - 1));
        if (position < firstItem) {
            // 第一种可能:跳转位置在第一个可见位置之前
            recyclerView.scrollToPosition(position);
        } else if (position <= lastItem) {
            // 第二种可能:跳转位置在第一个可见位置之后，最后一个可见项之前
            int movePosition = position - firstItem;
            if (movePosition >= 0 && movePosition < recyclerView.getChildCount()) {
                int top = recyclerView.getChildAt(movePosition).getTop();
                recyclerView.scrollBy(0, top - DensityUtil.dp2px(28)); // 下滑,28为悬浮ItemDecoration高度
            }
        } else {
            // 第三种可能:跳转位置在最后可见项之后;先滑动显示目标item，然后在addOnLayoutChangeListener监听中再次调用moveToPosition滑到顶部（moveToPosition就在addOnScrollListener中监听）
            recyclerView.scrollToPosition(position);
            mToPosition = position;
            mShouldScroll = true;
        }
    }

    private void moveSideBarTip(float y) {
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getViewDataBinding().sideTipView.getLayoutParams();
        layoutParams.topMargin = (int) y - DensityUtil.dp2px(10);
        getViewDataBinding().sideTipView.setLayoutParams(layoutParams);
    }

    /**
     * 接收点击保存消息推送
     *
     * @param afterItem 更新项目
     */
    @OnMessage(value = Options.MSG_SAVE_ITEM, always = true)
    public void onItemSaveButtonClick(T afterItem) {
        if (mSelectPosition > -1) {
            DataLoader.update(mDao, afterItem, new DataCallback<T>() {
                @Override
                public void success(@Nullable T data) {
                    mAdapter.getData().set(mSelectPosition, afterItem);
                    mAdapter.notifyItemChanged(mSelectPosition);
                    LegoMessageManager.getInstance().sendMessage(Options.MSG_SELECT_ITEM, afterItem);
                    DataControlResult result = new DataControlResult<>(data);
                    LegoMessageManager.getInstance().sendMessage(Options.MSG_SAVE_ITEM_RESULT, result);
                    showToast("更新成功", TOAST_SUCCESS);
                }

                @Override
                public void error(@Nullable String errorMessage) {
                    showToast("更新失败", TOAST_ERROR);
                    DataControlResult result = new DataControlResult<>(null, errorMessage);
                    LegoMessageManager.getInstance().sendMessage(Options.MSG_SAVE_ITEM_RESULT, result);
                }
            });
        }
    }

    /**
     * 添加数据
     *
     * @param newItem 新数据
     */
    @OnMessage(value = Options.MSG_ADD_ITEM, always = true)
    public void onAddItemButtonClick(T newItem) {
        DataLoader.save(mDao, newItem, new DataCallback<T>() {
            @Override
            public void success(@Nullable T data) {
                mAdapter.addItem(newItem);
                DataControlResult result = new DataControlResult<>(data);
                LegoMessageManager.getInstance().sendMessage(Options.MSG_ADD_ITEM_RESULT, result);
                showToast("保存成功", TOAST_SUCCESS);
            }

            @Override
            public void error(@Nullable String errorMessage) {
                showToast("保存失败", TOAST_ERROR);
                DataControlResult result = new DataControlResult<>(null, errorMessage);
                LegoMessageManager.getInstance().sendMessage(Options.MSG_ADD_ITEM_RESULT, result);
            }
        });
    }

    /**
     * 接收点击删除消息推送
     */
    @OnMessage(value = Options.MSG_DELETE_ITEM, always = true)
    public void onItemDeleteButtonClick() {
        if (mSelectPosition > -1) {
            T item = mAdapter.getData().get(mSelectPosition);
            DataLoader.delete(mDao, item, new DataCallback<T>() {
                @Override
                public void success(@Nullable T data) {
                    mAdapter.deleteItem(mSelectPosition);
                    mSelectPosition = -1;
                    DataControlResult result = new DataControlResult<>(data);
                    LegoMessageManager.getInstance().sendMessage(Options.MSG_DELETE_ITEM_RESULT, result);
                    showToast("删除成功", TOAST_SUCCESS);
                }

                @Override
                public void error(@Nullable String errorMessage) {
                    showToast("删除失败", TOAST_ERROR);
                    DataControlResult result = new DataControlResult<>(null, errorMessage);
                    LegoMessageManager.getInstance().sendMessage(Options.MSG_DELETE_ITEM_RESULT, result);
                }
            });
        }
    }

    /**
     * 接收点击全部删除消息推送
     *
     * @param param 删除条件
     */
    @OnMessage(value = Options.MSG_DELETE_ALL, always = true)
    public void onDeleteAllButtonClick(@Nullable String param) {
        DataLoader.delete(mDao, param, new DataCallback<T>() {
            @Override
            public void success(@Nullable T data) {
                mSelectPosition = -1;
                mAdapter.getData().clear();
                mAdapter.notifyDataSetChanged();
                showToast("删除成功", TOAST_SUCCESS);
            }

            @Override
            public void error(@Nullable String errorMessage) {
                showToast("删除失败", TOAST_ERROR);
            }
        });
    }

    /**
     * 仅清空所有ItemView显示
     */
    @OnMessage(value = Options.MSG_REMOVE_ALL_ITEM, always = true)
    public void receiveRemoveAllItemViewMessage() {
        mSelectPosition = -1;
        mAdapter.getData().clear();
        mAdapter.notifyDataSetChanged();
    }

    /**
     * 清除选中状态
     */
    @OnMessage(value = Options.MSG_REMOVE_SELECT_STATE,always = true)
    public void removeSelectState(){
        mSelectPosition = -1;
        for(T t:mAdapter.getData()){
            if(t.isSelected()){
                t.setSelected(false);
            }
        }
        mAdapter.notifyDataSetChanged();
    }
}